using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Security.Cryptography.Xml;

namespace PlainConcepts.Fx.Dnie.DigitalSign.Plugins
{
	/// <summary>
	/// Plugin to sign XML Documents
	/// </summary>
	public class XmlDigitalSigner
		:IDigitalSigner
    {
        #region Constructors

        /// <summary>
        /// Default constructor
        /// </summary>
        public XmlDigitalSigner()
        {
        }

        #endregion

        #region IDigitalSigner Members

        /// <summary>
        /// IDigintalSigner.Sign
        /// </summary>
        /// <param name="certificate">IDigintalSigner.Sign.certificate</param>
        /// <param name="pathDocument">IDigintalSigner.pathDocument</param>
        /// <param name="pathSignedDocument">IDigintalSigner.pathsignedDocument</param>
        public void Sign(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, string pathDocument, string pathSignedDocument)
		{
			//Validate input elements
			Asserts.IsNullOrEmpty(pathDocument, "pathDocument");
			Asserts.IsNullOrEmpty(pathSignedDocument, "pathSignedDocument");
			Asserts.IsValidPath(pathDocument);
			Asserts.IsValidExtension(pathDocument,this.Extension);
			

			//Create XML document
			XmlDocument xmlDoc = new XmlDocument();
			xmlDoc.PreserveWhitespace = true;
			xmlDoc.Load(pathDocument);


			// Creamos un objeto SignedXml partiendo del documento actual
			SignedXml signedXml = new SignedXml(xmlDoc);

			//Agregamos la clave
			signedXml.SigningKey = certificate.PrivateKey;

			//Creamos la referencia para firmar
			Reference reference = new Reference();
			reference.Uri = "";

			//Cremos el sobre de transformacion y se lo establecemos a la referencia
			XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
			reference.AddTransform(env);

			//establecemos la referencia
			signedXml.AddReference(reference);

			// Realizamos la firma
			signedXml.ComputeSignature();

			//Obtenemos la representacion
			XmlElement xmlDigitalSignature = signedXml.GetXml();

			//// Agregamos la firma al documento
			xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

			//guardamos nuevamente
			xmlDoc.Save(pathSignedDocument);
		}
		/// <summary>
		/// IDigitalSigner.Extension
		/// </summary>
		public string Extension
		{
			get { return ".xml"; }
		}

		#endregion
	}
}
